#include <Wire.h>
#define disk1 0x50    //Address of 24LC256 eeprom chip

byte posAddr;
byte countBytesPos;
byte modePin = 9;
char re[255];
void setup() {
	pinMode(modePin, INPUT);
	digitalWrite(modePin, HIGH);
	Serial.begin(9600);
	Wire.begin();
	//Serial.println("-"); // БЕЗ ЭТИХ СТРОК
	delay(50);				// НЕ ЗАВОДИТСЯ
	Serial.flush();
}
int list[] = {18,1,65,0,0,1,2,3,41,'H','e','l','l','o'};
String getParam(){
	for(byte i=0; i<255; i++) re[i] = 0x00;
	Serial.readBytesUntil(']',re,255);
	return String(re);
}

int getAddr(String p){
	posAddr = p.indexOf('(');
  	return p.substring(1,posAddr).toInt();
}

int getbytes(String p){
	countBytesPos = p.indexOf(')');
  	return p.substring(posAddr+1,countBytesPos).toInt();
}
void saveInt(int addr, String val){
	Serial.print(val);
	int i = val.toInt();
    unsigned int iNew = i;
    if(i<0){
      iNew=65535+i;
    }
  	byte buf[2];
  	buf[0] = iNew & 0xff;
  	if(iNew<0xFF){
  		buf[1] = 0x00;	
  	}else{
		buf[1] = (iNew >> 8) & 0xff;
	}
  writeEEPROM(addr, buf[0]);
  delay(5);
  writeEEPROM(addr+1, buf[1]);
}
// Главный цикл
void loop() {
	if (Serial.available()<1) return;
	//Serial.println("Hello");
	String param = getParam();
	int addr = getAddr(param);
	int bytes = getbytes(param);
	switch (param.charAt(0)) {
		case 'r':{
			Serial.print(readIntEEPROM(addr));
			if(bytes>1){
				for(int i = 1; i<bytes;i++){
					Serial.print("|");
					Serial.print(readIntEEPROM(addr+(i*2)));
				}
			}
		}
		break;
		case 'p':{
			for(int i = addr; i<addr+bytes;i++){
				char ch = readEEPROM(i);
				Serial.print((char)ch);
				if(ch == '|') break; 
			}
		}
		break;
		case 'w':{
			//for(int i = addr; i<addr+bytes;i++){
				int startData = param.indexOf('[');
				String data = String(param.substring(startData+1,param.length()));
				int po = data.indexOf('_');
				int st = 0;
				int saveAddr = addr;
				if(po<0) Serial.print(data);
				else{
					while (true){
						saveInt(saveAddr, data.substring(st,po));
						Serial.print("|");
						saveAddr=saveAddr+2;
						st = po+1;
						po = data.indexOf('_',st);	
						if(po<0) {
							saveInt(saveAddr, data.substring(st,data.length()));
							break;
						}
					}
				}
			//}
		}
		break;
		case 's':{
			int startData = param.indexOf('[');
			int saveAddr = addr;
			String data = String(param.substring(startData+1,param.length()));
			for(int i = 0; i<data.length();i++){
				Serial.print(data.charAt(i));
				writeEEPROM(saveAddr, (byte)data.charAt(i));
				saveAddr++;
				delay(5);
			}
			if(data.length()<bytes){
				for(int i = 0; i<bytes-data.length();i++){
					writeEEPROM(saveAddr, ' ');
					saveAddr++;
					delay(5);
				}
			}
		}
		break;
		case 'g':{
			Serial.print("Hi");
		}
		break;
	}
	Serial.println();
	Serial.flush();
}
void writeEEPROM(unsigned int eeaddress, byte data ) 
{
	Wire.beginTransmission(disk1);
	if(doubleAddress()){
		Wire.write((int)(eeaddress >> 8));       // MSB
  		Wire.write((int)(eeaddress & 0xFF));     // LSB
	} else  Wire.write(eeaddress);
	Wire.write(data);
	Wire.endTransmission();
	delay(3);
}
 
byte readEEPROM(unsigned int eeaddress ) 
{
  byte rdata = 0x00;
 
  Wire.beginTransmission(disk1);
  	if(doubleAddress()){
		Wire.write((int)(eeaddress >> 8));       // MSB
  		Wire.write((int)(eeaddress & 0xFF));     // LSB
	} else  Wire.write(eeaddress);
  Wire.endTransmission();
 
  Wire.requestFrom(disk1,1);
 
  if (Wire.available()) rdata = Wire.read();
  return rdata;
}

int readIntEEPROM(unsigned int eeaddress ) 
{
	byte buf[2];

	Wire.beginTransmission(disk1);
	if(doubleAddress()){
		Wire.write((int)(eeaddress >> 8));       // MSB
  		Wire.write((int)(eeaddress & 0xFF));     // LSB
	} else  Wire.write(eeaddress);
	Wire.endTransmission();

	Wire.requestFrom(disk1,2);
	unsigned int c = 0;
	buf[0] = Wire.read();
	buf[1] = Wire.read();
	memcpy(&c,buf,2);
    if(c > 32767){
      return c - 65535;
    }
	return c;
}

bool doubleAddress(){
	return digitalRead(modePin) == HIGH;
}
